package com.common.aliyun.oss.template;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import com.common.aliyun.oss.properties.OssProperties;
import com.zhengaz.common.core.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.Objects;

/**
 * @author zhengzg
 * @create 2023-09-18 9:51
 */
@Slf4j
public class OssTemplate {

    private final OssProperties ossProperties;

    private final OSS ossClient;

    private final static Date OSS_URL_EXPIRATION = DateUtils.addDays(new Date(), 365 * 10);

    public OssTemplate(OssProperties ossProperties) throws Exception {
        this.ossProperties = ossProperties;
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        ossClient = new OSSClientBuilder().build(ossProperties.getEndpoint(), credentialsProvider);
    }

    /**
     * 上传文件---去除URL中的？后的时间戳
     * @param file 文件
     * @return 文件的访问地址
     */
    public String upload(MultipartFile file) {
        createBucket();
        String fileName = uploadFile(file);
        String fileOssURL = getImgUrl(fileName);
        int firstChar = fileOssURL.indexOf("?");
        if (firstChar > 0) {
            fileOssURL = fileOssURL.substring(0, firstChar);
        }
        return fileOssURL;
    }
    /**
     * 当Bucket不存在时创建Bucket
     *
     * @throws OSSException 异常
     */
    private void createBucket() {
        try {
            if (!ossClient.doesBucketExist(ossProperties.getBucket())) {//判断是否存在该Bucket，不存在时再重新创建
                ossClient.createBucket(ossProperties.getBucket());
            }
        } catch (Exception e) {
            log.error("{}", "创建Bucket失败,请核对Bucket名称(规则：只能包含小写字母、数字和短横线，必须以小写字母和数字开头和结尾，长度在3-63之间)");
            throw new ServiceException("创建Bucket失败,请核对Bucket名称(规则：只能包含小写字母、数字和短横线，必须以小写字母和数字开头和结尾，长度在3-63之间)");
        }
    }
    /**
     * 上传到OSS服务器  如果同名文件会覆盖服务器上的
     * @param file 文件
     * @return 文件的访问地址
     */
    private String uploadFile(MultipartFile file) {
        String fileName = String.format(
                "%s.%s",
                UUID.randomUUID(),
                FilenameUtils.getExtension(file.getOriginalFilename()));
        try (InputStream inputStream = file.getInputStream()) {
            //创建上传Object的Metadata
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(inputStream.available());
            objectMetadata.setCacheControl("no-cache");
            objectMetadata.setHeader("Pragma", "no-cache");
            objectMetadata.setContentType(getContentType(FilenameUtils.getExtension("." + file.getOriginalFilename())));
            objectMetadata.setContentDisposition("inline;filename=" + fileName);
            //上传文件
            PutObjectResult putResult = ossClient.putObject(ossProperties.getBucket(), fileName, inputStream, objectMetadata);
            return fileName;
        } catch (Exception e) {
            log.error("{}", "上传文件失败");
            throw new ServiceException("上传文件失败");
        }
    }
    /**
     * 获得文件路径
     * @param fileUrl  文件的URL
     * @return 文件的路径
     */
    private String getImgUrl(String fileUrl) {
        if (StrUtil.isEmpty(fileUrl)) {
            log.error("{}", "文件地址为空");
            throw new RuntimeException("文件地址为空");
        }
        //获取oss图片URL失败
        URL url = ossClient.generatePresignedUrl(ossProperties.getBucket(), fileUrl, OSS_URL_EXPIRATION);
        if (Objects.isNull(url)) {
            log.error("{}", "获取oss文件URL失败");
            throw new ServiceException("获取oss文件URL失败");
        }
        return url.toString();
    }
    /**
     * 判断OSS服务文件上传时文件的contentType
     *
     * @param FilenameExtension 文件后缀
     * @return 后缀
     */
    private static String getContentType(String FilenameExtension) {
        if (FilenameExtension.equalsIgnoreCase("bmp")) {
            return "image/bmp";
        }
        if (FilenameExtension.equalsIgnoreCase("gif")) {
            return "image/gif";
        }
        if (FilenameExtension.equalsIgnoreCase("jpeg") ||
                FilenameExtension.equalsIgnoreCase("jpg") ||
                FilenameExtension.equalsIgnoreCase("png")) {
            return "image/jpeg";
        }
        if (FilenameExtension.equalsIgnoreCase("html")) {
            return "text/html";
        }
        if (FilenameExtension.equalsIgnoreCase("txt")) {
            return "text/plain";
        }
        if (FilenameExtension.equalsIgnoreCase("vsd")) {
            return "application/vnd.visio";
        }
        if (FilenameExtension.equalsIgnoreCase("pptx") ||
                FilenameExtension.equalsIgnoreCase("ppt")) {
            return "application/vnd.ms-powerpoint";
        }
        if (FilenameExtension.equalsIgnoreCase("docx") ||
                FilenameExtension.equalsIgnoreCase("doc")) {
            return "application/msword";
        }
        if (FilenameExtension.equalsIgnoreCase("xml")) {
            return "text/xml";
        }
        return "image/jpeg";
    }


}
